package cn.scantd.core.ast;

import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;

import cn.scantd.core.attrs.Scope;
import cn.scantd.core.model.JavaField;
import cn.scantd.core.model.JavaMethod;
import cn.scantd.core.model.JavaType;
import cn.scantd.core.util.EnumUtil;

/**
 * Java File AST 访问类
 * 
 * @author xuq
 * @date 2015年10月5日
 * @version 1.0
 */
public class JavaFileAST extends ASTVisitor {

    /**
     * 解析获得的javaType信息
     */
    private JavaType javaType;
    
    /**
     * 需要访问的作用范围
     */
    private Scope scope;
    
    /**
     * 初始化访问作用范围
     * 
     * @param scope 访问范围
     */
    public JavaFileAST(Scope scope) {
        this.scope = scope;
    }
    
    @Override
    public boolean visit(FieldDeclaration node) {
        for (Object obj : node.fragments()) {
            VariableDeclarationFragment v = (VariableDeclarationFragment) obj;
            JavaField javaField = new JavaField(node, v);
            if (EnumUtil.canRead(scope, javaField.getScope())) {
                javaType.addField(javaField);
                return true;
            } else {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean visit(MethodDeclaration node) {
        JavaMethod javaMethod = new JavaMethod(node);
        if (EnumUtil.canRead(scope, javaMethod.getScope())) {
            javaType.addMethod(javaMethod);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean visit(TypeDeclaration node) {
        javaType = new JavaType(node);
        if (EnumUtil.canRead(scope, javaType.getScope())) {
            return true;
        } else {
            return false;
        }
    }
    
    @Override
    public boolean visit(AnnotationTypeDeclaration node) {
    	// skip annotation type.
        return false;
    }

    public JavaType getJavaType() {
        return this.javaType;
    }

}
